#include "declare.hpp"

// 文本文件的读取
bool MapSystem::_ReadTextFile()
{
    std::string pathfile = "./data/GTBL.txt";
    std::ifstream infile(pathfile); // 文本模式打开文件
    if (!infile)
    {
        _log(ERROR, "Unable to open file %s", pathfile.c_str());
        return false; // 文件打开失败，返回false
    }

    INT16U usRecSize, usRoadNameSize;
    INT32U ulLinkID, ulStaNodeInfo;
    std::string roadName;

    _log(INFO, "正在读取文件%s", pathfile.c_str());
    sleep(1);

    if (!_nodeList.empty())
        _nodeList.clear();

    size_t count = 0;
    while (infile >> usRecSize >> ulLinkID >> usRoadNameSize >> ulStaNodeInfo)
    {
        std::getline(infile >> std::ws, roadName); // 读取道路名称,跳过空白符
        if (!roadName.empty() && roadName[0] == ' ')
        {
            roadName = roadName.substr(1); // 去掉前面的空格
        }

        // 创建节点并添加到链表中
        Node newNode(usRecSize, ulLinkID, usRoadNameSize, ulStaNodeInfo, roadName);
        _nodeList.push_back(newNode);
        count++;
    }
    _log(INFO, "成功读取文件%s,读取了%d条数据", pathfile.c_str(), count);
    return true; // 文件读取成功，返回true
}

// 写入文本文件
bool MapSystem::_InputFile()
{
    std::ofstream outfile("output.dat", std::ios::out | std::ios::trunc);
    // 检查文件是否成功打开
    if (!outfile.is_open())
    {
        _log(ERROR, "无法打开文件output.dat!");
        return false; // 文件打开失败，返回false
    }
    _log(INFO, "正在写入文件output.dat");
    sleep(1);
    // 遍历数组并写入文件
    for (const auto &node : _vector_array)
    {
        outfile << node._usRecSize << " "
                << node._ulLinkID << " "
                << node._usRoadNameSize << " "
                << node._ulStaNodeInfo << " "
                << node._pcRoadName << std::endl; // 每个节点的信息写入一行
    }
    // 关闭文件
    outfile.close();
    return true; // 文件写入成功，返回true
}

// 写入二进制文件
bool MapSystem::_OutputBinaryFile()
{
    std::ofstream outfile("output.bin", std::ios::out | std::ios::binary | std::ios::trunc);

    // 检查文件是否成功打开
    if (!outfile.is_open())
    {
        _log(ERROR, "无法打开文件output.bin!");
        return false; // 文件打开失败，返回false
    }

    _log(INFO, "正在写入文件output.bin");
    sleep(1);

    // 遍历链表并写入文件
    for (const auto &node : _nodeList)
    {
        // 写入基本数据
        outfile.write(reinterpret_cast<const char *>(&node._usRecSize), sizeof(node._usRecSize));
        outfile.write(reinterpret_cast<const char *>(&node._ulLinkID), sizeof(node._ulLinkID));
        outfile.write(reinterpret_cast<const char *>(&node._usRoadNameSize), sizeof(node._usRoadNameSize));
        outfile.write(reinterpret_cast<const char *>(&node._ulStaNodeInfo), sizeof(node._ulStaNodeInfo));

        // 写入道路名称的长度
        size_t nameLength = node._pcRoadName.size();
        outfile.write(reinterpret_cast<const char *>(&nameLength), sizeof(nameLength));

        // 写入道路名称数据
        outfile.write(node._pcRoadName.c_str(), nameLength);
    }
    // 关闭文件
    outfile.close();
    return true; // 文件写入成功，返回true
}

inline INT16U MapSystem::_swapEndian(INT16U value)
{
    return (value >> 8) | (value << 8);
}

inline INT32U MapSystem::_swapEndian(INT32U value)
{
    return ((value >> 24) & 0x000000FF) |
           ((value >> 8) & 0x0000FF00) |
           ((value << 8) & 0x00FF0000) |
           ((value << 24) & 0xFF000000);
}

// 读取二进制文件
bool MapSystem::_ReadBinaryFile()
{
    std::string pathfile = "./data/GTBL.bin";
    std::ifstream infile(pathfile, std::ios::in | std::ios::binary); // 二进制模式打开文件

    // 检查文件是否成功打开
    if (!infile.is_open())
    {
        _log(ERROR, "无法打开文件%s!", pathfile.c_str());
        return false; // 文件打开失败，返回false
    }

    _log(INFO, "正在读取文件%s", pathfile.c_str());
    sleep(1);
    size_t count = 0;
    while (infile.peek() != EOF) // 检查是否到达文件结尾
    {
        Node node; // 创建一个节点来存储读取的数据
        // 读取基本数据
        infile.read(reinterpret_cast<char *>(&node._usRecSize), sizeof(node._usRecSize));
        infile.read(reinterpret_cast<char *>(&node._ulLinkID), sizeof(node._ulLinkID));
        infile.read(reinterpret_cast<char *>(&node._usRoadNameSize), sizeof(node._usRoadNameSize));
        infile.read(reinterpret_cast<char *>(&node._ulStaNodeInfo), sizeof(node._ulStaNodeInfo));

        // 读取道路名称的长度
        size_t nameLength;
        infile.read(reinterpret_cast<char *>(&nameLength), sizeof(nameLength));

        // 确保读取的名称长度不超过合法范围
        if (nameLength > 255) // 假设最大长度为255
        {
            _log(ERROR, "道路名称长度不合法: %zu", nameLength);
            continue; // 跳过当前节点
        }

        // 读取道路名称数据
        std::vector<char> nameBuffer(nameLength);
        infile.read(nameBuffer.data(), nameLength);
        node._pcRoadName = std::string(nameBuffer.data(), nameLength); // 将字符数组转换为字符串

        // 将节点添加到链表中
        _nodeList.push_back(node);
        count++;
    }
    _log(INFO, "成功读取文件%s,读取了%d条数据", pathfile.c_str(), count);
    infile.close();
    return true; // 文件读取成功，返回true
}

// 写入文件
bool MapSystem::_WriteFile()
{
    if (_vector_array.empty())
    {
        this->_log(INFO, "没有信息需要更新");
        return false; // 没有数据需要写入，返回false
    }
    _InputFile(); // 将排序后的数据写入 output.dat
    this->_log(INFO, "更新成功,信息已经写到output.dat中");
    return true; // 数据写入成功，返回true
}
